use crate::utils::cmd::{get_shell, probe_cmd};
use anyhow::{Error, Result, format_err};
use network_interface::NetworkInterfaceConfig;
use regex::Regex;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::hash::Hash;
use std::net::Ipv4Addr;
use std::str::FromStr;
use std::sync::{Arc, OnceLock};

static STR_MAP: OnceLock<HashMap<&'static str, u8>> = OnceLock::new();

#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
struct IPPort {
    pub ip: Ipv4Addr,
    pub port: u16,
}

impl FromStr for IPPort {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let err = Err("error ip:port format".to_string());
        let items = s.split(":").collect::<Vec<&str>>();
        if items.len() != 2 {
            return err;
        }
        let result_ip: Ipv4Addr;
        let result_port: u16;
        if let Ok(ip) = items[0].parse::<Ipv4Addr>() {
            result_ip = ip;
        } else {
            return err;
        }
        if let Ok(port) = items[1].parse::<u16>() {
            result_port = port;
        } else {
            return err;
        }
        Ok(IPPort {
            ip: result_ip,
            port: result_port,
        })
    }
}

#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
pub struct IPv4Cidr {
    pub ip: Ipv4Addr,
    pub netmask: u8,
}

impl PartialOrd for IPv4Cidr {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.netmask > other.netmask {
            Some(Ordering::Greater)
        } else if self.netmask < other.netmask {
            Some(Ordering::Less)
        } else {
            let bit_self = self.ip.to_bits();
            let bit_other = other.ip.to_bits();
            if bit_self == bit_other {
                Some(Ordering::Equal)
            } else if bit_self >= bit_other {
                Some(Ordering::Greater)
            } else {
                Some(Ordering::Less)
            }
        }
    }
}

impl Ord for IPv4Cidr {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl IPv4Cidr {
    pub fn new(ip: Ipv4Addr, netmask: u8) -> Self {
        let ip_bits = ip.to_bits();
        if (ip_bits & netmask_u32(netmask, true)) > 0 {
            panic!("IPv4Cidr does not contain netmask {}", netmask);
        }
        Self { ip, netmask }
    }

    pub fn ip(&self) -> &Ipv4Addr {
        &self.ip
    }

    /// 获取子网掩码长度
    pub fn netmask(&self) -> u8 {
        self.netmask
    }

    /// 判断一个IP地址是否属于本网段中
    pub fn contains(&self, ip: &Ipv4Addr) -> bool {
        if ip.to_bits() & netmask_u32(self.netmask, false) == self.ip.to_bits()
            && ip.to_bits() & netmask_u32(self.netmask, true) > 0
        {
            true
        } else {
            false
        }
    }
}

impl FromStr for IPv4Cidr {
    type Err = String;

    /// 支持的格式为：192.168.0.0/16和192.168/16
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let err = Err("Invalid IPv4 CIDR format".to_string());
        if !s.contains("/") {
            return err;
        }
        let input = s.to_string();
        let items = input.trim().split('/').collect::<Vec<&str>>();
        if items.len() != 2 {
            return err;
        }
        let cidr = Regex::new(r##"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])){0,3}$"##).unwrap();
        if !cidr.is_match(items[0]) {
            return err;
        }
        let result = items[1].parse::<u8>();
        let netmask = match result {
            Ok(u) => {
                if u > 32 {
                    return err;
                }
                u
            }
            Err(e) => {
                return Err(e.to_string());
            }
        };
        let mut bits = items[0]
            .split('.')
            .map(|s| {
                s.parse::<u8>()
                    .expect(&format!("Invalid IPv4 CIDR format: {}", s))
            })
            .collect::<Vec<u8>>();
        if bits.len() > 4 || bits.len() == 0 {
            return Err("Invalid IPv4 CIDR format".to_string());
        } else if items.len() < 4 {
            let l = items.len();
            for _ in l..5 {
                bits.push(0);
            }
        }
        let ip = Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]);
        let ip_bits = ip.to_bits();
        if (ip_bits & netmask_u32(netmask, true)) > 0 {
            err
        } else {
            Ok(IPv4Cidr { ip, netmask })
        }
    }
}

#[derive(Debug, Hash, Eq, PartialEq)]
/// 单条路由的定义
pub struct RouteItem {
    /// 目的网段
    dist: IPv4Cidr,
    /// 网卡
    dev: String,
    /// 下一跳的IP地址
    next_hop: String,
}

impl RouteItem {
    pub fn new(dist: IPv4Cidr, dev: String, next_hop: String) -> Self {
        Self {
            dist,
            dev,
            next_hop,
        }
    }
}

impl PartialOrd for RouteItem {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.dist.partial_cmp(&other.dist)
    }
}

impl Ord for RouteItem {
    fn cmp(&self, other: &Self) -> Ordering {
        self.dist.cmp(&other.dist)
    }
}

/// 路由表定义
#[derive(Debug)]
pub struct RouteTable {
    route_items: Vec<Arc<RouteItem>>,
    set: HashSet<Arc<RouteItem>>,
    order: bool,
}

impl RouteTable {
    pub fn new() -> Self {
        Self {
            route_items: Vec::new(),
            order: false,
            set: HashSet::new(),
        }
    }

    pub fn len(&self) -> usize {
        self.route_items.len()
    }

    /// 对路由表中的路由项进行排序，适配范围小的路由项在前，适配范围大的路由项在后
    pub fn sort(&mut self) {
        self.route_items.sort_by(|a, b| b.cmp(a));
        self.order = true;
    }

    /// 给出匹配dest_ip的路由项
    pub fn match_route(&mut self, dest_ip: Ipv4Addr) -> Option<&RouteItem> {
        if !self.order {
            self.sort();
        }
        for item in &self.route_items {
            if item.dist.contains(&dest_ip) {
                return Some(item);
            }
        }
        None
    }

    pub fn add(&mut self, route_item: RouteItem) {
        let ri = Arc::new(route_item);
        if self.set.contains(&ri) {
            return;
        }
        self.set.insert(ri.clone());
        self.route_items.push(ri);
        self.order = false;
    }

    pub fn iter(&self) -> RouteTableIterator {
        RouteTableIterator {
            table: self,
            index: 0,
            size: self.route_items.len(),
        }
    }
}

/// 路由表遍历中间体
pub struct RouteTableIterator<'a> {
    table: &'a RouteTable,
    index: usize,
    size: usize,
}

/// 为路由表遍历中间体实现遍历特型
impl<'a> Iterator for RouteTableIterator<'a> {
    type Item = Arc<RouteItem>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.size == 0 || self.index >= self.size {
            None
        } else {
            let r = self.table.route_items.get(self.index).unwrap().clone();
            self.index += 1;
            Some(r)
        }
    }
}

/// 根据子网掩码长度生成对应的u32掩码数字
pub fn netmask_u32(mask_len: u8, reversal: bool) -> u32 {
    if mask_len > 32 {
        panic!("netmask bits must be less than 32");
    }
    let mut result = 0u32;
    for i in 0..32 {
        if i < mask_len {
            result |= 1u32 << i;
        } else {
            result <<= 1;
        }
    }
    if reversal { !result } else { result }
}

/// 解析格式为255.255.240.0的子网掩码，给出子网掩码的长度
fn parse_netmask(netmask: &str) -> Result<u8, String> {
    let sss = netmask.split(".").collect::<Vec<&str>>();
    let mut result: u8 = 0;
    let mut is_finish = false;
    for s in sss.iter() {
        if let Some(l) = get_str_len_map().get(s) {
            if *l > 0u8 && is_finish {
                return Err("netmask format error".to_string());
            }
            result += l;
            if *l != 8u8 {
                is_finish = true;
            }
        } else {
            return Err("netmask format error".to_string());
        }
    }
    Ok(result)
}

/// 解析系统路由表 macos版本
#[cfg(target_os = "macos")]
pub fn parse_route() -> Result<RouteTable, Error> {
    let cmd_result = std::process::Command::new(get_shell())
        .arg("-c")
        .arg(r##"netstat -nr -f inet | grep -E "^([0-9]|default)" | awk '{print $1,$2,$4}' | sed 's|default|0.0.0.0/0|g'"##)
        .output()?;
    if !cmd_result.status.success() {
        let s = String::from_utf8(cmd_result.stderr)?;
        return Err(format_err!("netstat error: {}", s));
    }
    let interfaces = network_interface::NetworkInterface::show().unwrap_or(Vec::new());
    let mut map_dev_ip = HashMap::<String, String>::new();
    // 拿到路由表，分离出网卡名
    for interface in &interfaces {
        for addr in &interface.addr {
            if addr.ip().is_ipv4() {
                map_dev_ip.insert(interface.name.clone(), addr.ip().to_string());
            }
        }
    }
    // 逐条解析路由
    let mut result = RouteTable::new();
    let output = String::from_utf8(cmd_result.stdout)?;
    let lines = output.split("\n").collect::<Vec<&str>>();
    for line in lines {
        let items = line.split(" ").collect::<Vec<&str>>();
        if items.len() != 3 {
            continue;
        }
        if items[1].parse::<Ipv4Addr>().is_ok() || map_dev_ip.contains_key(&items[1].to_string()) {
            if let Ok(netmask) = items[0].parse::<IPv4Cidr>() {
                let mut next_hop = String::new();
                if let Some(dev) = map_dev_ip.get(&items[2].to_string()) {
                    next_hop.push_str(dev);
                } else {
                    next_hop.push_str(items[2]);
                }
                let ri = RouteItem::new(netmask, items[2].to_string(), next_hop);
                result.add(ri);
            }
        }
    }
    // 路由排序
    result.sort();
    Ok(result)
}

/// 解析系统路由表 linux版本
///#[cfg(target_os = "linux")]
pub fn parse_route_linux() -> Result<RouteTable, Error> {
    let interfaces = network_interface::NetworkInterface::show().unwrap_or(Vec::new());
    let mut map_dev_ip = HashMap::<String, String>::new();
    interfaces.iter().for_each(|x| {
        for addr in &x.addr {
            if addr.ip().is_ipv4() {
                map_dev_ip.insert(x.name.clone(), addr.ip().to_string());
            }
        }
    });
    let mut result = RouteTable::new();
    if probe_cmd(&"ip".to_string()) {
        // 如果有ip命令
        let cmd_output = std::process::Command::new(get_shell())
            .arg("-c")
            .arg(r##"ip route | grep -E '^([0-9]|default)' | sed 's|default|0.0.0.0/0|g'"##)
            .output()?;
        if !cmd_output.status.success() {
            let s = String::from_utf8(cmd_output.stderr)?;
            return Err(format_err!("netstat error: {}", s));
        }
        let output = String::from_utf8(cmd_output.stdout)?;
        let reg_via = Regex::new("via (?P<via>(?:[0-9]+\\.){3}(?:[0-9]+))")?;
        let reg_dev = Regex::new("dev (?P<dev>[a-z0-9]+)")?;
        let reg_src = Regex::new("src (?P<src>(?:[0-9]+\\.){3}(?:[0-9]+))")?;
        let reg_cidr = Regex::new("^([0-9]+\\.){3}([0-9]+)(/[0-9]*|)")?;
        for line in output.split("\n").collect::<Vec<&str>>() {
            let dest: IPv4Cidr;
            let dev: String;
            let next_hop: String;
            if let Some(c) = reg_cidr.find(line) {
                let mut cidr_str = String::from(c.as_str());
                if let None = cidr_str.find("/") {
                    cidr_str.push_str(&"/32".to_string());
                }
                if let Ok(cidr) = cidr_str.parse::<IPv4Cidr>() {
                    dest = cidr
                } else {
                    continue;
                }
            } else {
                continue;
            }
            if let Some(dev_cap) = reg_dev.captures(line) {
                dev = dev_cap["dev"].to_string();
            } else {
                continue;
            }
            // 下一跳的优先级 via > src > dev's ip
            if let Some(via_cap) = reg_via.captures(line) {
                next_hop = via_cap["via"].to_string();
            } else if let Some(src_cap) = reg_src.captures(line) {
                next_hop = src_cap["src"].to_string();
            } else {
                if let Some(s) = map_dev_ip.get(&dev) {
                    next_hop = s.to_string();
                } else {
                    continue;
                }
            }
            result.add(RouteItem::new(dest, dev, next_hop));
        }
        result.sort();
        Ok(result)
    } else if probe_cmd(&"route".to_string()) {
        // 如果有route命令
        let cmd_output = std::process::Command::new(get_shell())
            .arg("-c")
            .arg(r##"route -n | grep -E '^[0-9]' | awk '{print $1,$3,$2,$8}'"##)
            .output()?;
        if !cmd_output.status.success() {
            let s = String::from_utf8(cmd_output.stderr)?;
            return Err(format_err!("netstat error: {}", s));
        }
        let output = String::from_utf8(cmd_output.stdout)?;
        for line in output.split("\n").collect::<Vec<&str>>() {
            let dest: IPv4Cidr;
            let next_hop: String;
            let items = line.split(" ").collect::<Vec<&str>>();
            if items.len() != 4 {
                continue;
            }
            let mut cidr_str = String::new();
            cidr_str.push_str(items[0]);
            cidr_str.push_str("/");
            if let Ok(l) = parse_netmask(items[1]) {
                cidr_str.push_str(l.to_string().as_str());
            } else {
                continue;
            }
            let dev: String = items[3].to_string();
            if let Ok(c) = cidr_str.parse::<IPv4Cidr>() {
                dest = c;
            } else {
                continue;
            }
            if let Ok(ip) = items[2].parse::<Ipv4Addr>() {
                next_hop = ip.to_string();
            } else {
                if let Some(ip) = map_dev_ip.get(&dev) {
                    next_hop = ip.to_string();
                } else {
                    continue;
                }
            }
            result.add(RouteItem::new(dest, dev, next_hop));
        }
        result.sort();
        Ok(result)
    } else {
        Err(format_err!("need route or ip command"))
    }
}

/// 解析系统路由表 windows版本
//#[cfg(target_os = "windows")]
pub fn parse_route_windows() -> Result<RouteTable, Error> {
    let interfaces = network_interface::NetworkInterface::show().unwrap_or(Vec::new());
    let mut map_ip_dev = HashMap::<String, String>::new();
    interfaces.iter().for_each(|x| {
        for addr in &x.addr {
            if addr.ip().is_ipv4() {
                map_ip_dev.insert(addr.ip().to_string(), x.name.clone());
            }
        }
    });
    let mut cmd_output = std::process::Command::new("cmd")
        .arg("/C")
        .arg("chcp 65001 && route print -4")
        .output()
        .unwrap();
    if !cmd_output.status.success() {
        let s = String::from_utf8(cmd_output.stderr)?;
        return Err(format_err!("netstat error: {}", s));
    }
    let output = String::from_utf8(cmd_output.stdout)?;
    let filter = Regex::new(
        "^ +(?P<dest>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?P<netmask>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?P<next>\\S+) +(?P<from>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?:[0-9]+)$",
    )?;
    let is_ipv4 = Regex::new("([0-9]+\\.){3}([0-9]+)")?;
    let mut result = RouteTable::new();
    for line in output.split("\n").collect::<Vec<&str>>() {
        if let Some(c) = filter.captures(line) {
            println!(
                "dest: ({}) netmask: ({}) next: ({}) from: ({})",
                &c["dest"], &c["netmask"], &c["next"], &c["from"]
            );
            let dest: IPv4Cidr;
            let next_hop: String;
            let dev: String;
            let mut cidr_str = (&c["dest"]).to_string();
            if let Ok(netmask_len) = parse_netmask(&c["netmask"]) {
                cidr_str.push_str("/");
                cidr_str.push_str(&netmask_len.to_string());
            } else {
                continue;
            }
            if let Ok(cidr) = cidr_str.parse::<IPv4Cidr>() {
                dest = cidr
            } else {
                continue;
            }
            if let Some(from) = map_ip_dev.get(&c["from"].to_string()) {
                dev = from.to_string();
            } else {
                continue;
            }
            if is_ipv4.is_match(&c["next"]) {
                next_hop = c["next"].to_string();
            } else {
                next_hop = c["from"].to_string();
            }
            result.add(RouteItem::new(dest, dev, next_hop));
        }
    }
    result.sort();
    Ok(result)
}

fn get_str_len_map() -> &'static HashMap<&'static str, u8> {
    STR_MAP.get_or_init(|| {
        return HashMap::from([
            ("ff", 8),
            ("fe", 7),
            ("fc", 6),
            ("f8", 5),
            ("f0", 4),
            ("e0", 3),
            ("c0", 2),
            ("80", 1),
            ("00", 0),
            ("0", 0),
            ("128", 1),
            ("192", 2),
            ("224", 3),
            ("240", 4),
            ("248", 5),
            ("252", 6),
            ("254", 7),
            ("255", 8),
        ]);
    })
}

#[test]
fn test_parse_route() {
    //     let output = "0.0.0.0/0 via 172.16.175.253 dev eth0 proto dhcp src 172.16.163.87 metric 100
    // 10.10.10.0/24 dev wg0 proto kernel scope link src 10.10.10.1
    // 10.126.126.0/24 dev tun0 proto kernel scope link src 10.126.126.1
    // 172.16.30.0/24 dev tun0 proto static metric 65535
    // 172.16.40.0/24 dev tun0 proto static metric 65535
    // 172.16.50.0/24 dev tun0 proto static metric 65535
    // 172.16.100.0/24 dev tun0 proto static metric 65535
    // 172.16.130.0/24 dev tun0 proto static metric 65535
    // 172.16.160.0/20 dev eth0 proto kernel scope link src 172.16.163.87 metric 100
    // 172.16.250.0/24 dev br-1edce47383a8 proto kernel scope link src 172.16.250.1
    // 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
    // 192.168.10.1 dev wg0 scope link";
    //
    //     let reg_via = Regex::new("via (([0-9]+\\.){3}([0-9]+))").unwrap();
    //     let reg_dev = Regex::new("dev [a-z0-9]+").unwrap();
    //     let reg_src = Regex::new("src ([0-9]+\\.){3}([0-9]+)").unwrap();
    //     let reg_cidr = Regex::new("^([0-9]+\\.){3}([0-9]+)(/[0-9]*|)").unwrap();
    //     for line in output.split("\n") {
    //         if let Some(via) = reg_via.find(line) {
    //             println!("{}", via.as_str());
    //         }
    //         if let Some(cidr) = reg_cidr.find(line) {
    //             println!("{}", cidr.as_str().trim());
    //         }
    //         if let Some(dev) = reg_dev.find(line) {
    //             println!("{}", dev.as_str().trim());
    //         }
    //         if let Some(src) = reg_src.find(line) {
    //             println!("{}", src.as_str().trim());
    //         }
    //         println!("-------------------------------")
    //     }
    //
    //     let output2 = "0.0.0.0 0.0.0.0 172.16.175.253 eth0
    // 10.10.10.0 255.255.255.0 0.0.0.0 wg0
    // 10.126.126.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.30.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.40.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.50.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.100.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.130.0 255.255.255.0 0.0.0.0 tun0
    // 172.16.160.0 255.255.240.0 0.0.0.0 eth0
    // 172.16.250.0 255.255.255.0 0.0.0.0 br-1edce47383a8
    // 172.17.0.0 255.255.0.0 0.0.0.0 docker0
    // 192.168.10.1 255.255.255.255 0.0.0.0 wg0";
    //     // 路由表处理逻辑：由$1 $2确定目的网段，$3如果是0.0.0.0，就抓取$4的IP地址
    //
    //     let mut rt1 = RouteTable::new();
    //     for line in output2.split("\n") {
    //         let items = line.split(" ").collect::<Vec<&str>>();
    //         if items.len() != 4 {
    //             continue;
    //         }
    //         let mut cidr_str = String::new();
    //         cidr_str.push_str(items[0]);
    //         cidr_str.push_str("/");
    //         if let Ok(l) = parse_netmask(items[1]) {
    //             cidr_str.push_str(l.to_string().as_str());
    //         } else {
    //             continue;
    //         }
    //         let cidr: IPv4Cidr;
    //         let dev: String = items[3].to_string();
    //         let next_hop: String;
    //         if let Ok(c) = cidr_str.parse::<IPv4Cidr>() {
    //             cidr = c;
    //         } else {
    //             continue;
    //         }
    //         if let Ok(ip) = items[2].parse::<Ipv4Addr>() {
    //             next_hop = ip.to_string();
    //         } else {
    //             next_hop = String::from("");
    //         }
    //         rt1.add(RouteItem {
    //             dist: cidr,
    //             dev,
    //             next_hop,
    //         })
    //     }

    let output3 = "===========================================================================
接口列表
  9...00 ff 3b 15 08 17 ......Sangfor SSL VPN CS Support System VNIC
 46...02 50 f2 00 00 02 ......iNode VPN Virtual NIC
 10...00 ff 7c 5b 26 73 ......Sangfor aTrust VNIC
 53...........................et_9_rvqe Tunnel
 11...12 34 56 78 90 21 ......Realtek PCIe 2.5GbE Family Controller
  5...0a 00 27 00 00 05 ......VirtualBox Host-Only Ethernet Adapter
 39...00 ff 14 ec 11 1c ......TAP-Windows Adapter V9
  2...00 50 56 c0 00 01 ......VMware Virtual Ethernet Adapter for VMnet1
  4...00 50 56 c0 00 08 ......VMware Virtual Ethernet Adapter for VMnet8
  1...........................Software Loopback Interface 1
===========================================================================

IPv4 路由表
===========================================================================
活动路由:
网络目标        网络掩码          网关       接口   跃点数
          0.0.0.0          0.0.0.0      172.16.50.1     172.16.50.83    281
          2.0.0.0    255.255.255.0            在链路上           2.0.0.1    257
          2.0.0.1  255.255.255.255            在链路上           2.0.0.1    257
        2.0.0.255  255.255.255.255            在链路上           2.0.0.1    257
        10.1.1.42  255.255.255.255     10.1.114.144     10.1.114.146    257
        10.1.1.50  255.255.255.255     10.1.114.144     10.1.114.146    257
        10.1.1.66  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.139  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.168  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.174  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.221  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.238  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.1.248  255.255.255.255     10.1.114.144     10.1.114.146    257
        10.1.16.2  255.255.255.255     10.1.114.144     10.1.114.146    257
        10.1.16.4  255.255.255.254     10.1.114.144     10.1.114.146    257
        10.1.20.6  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.21.34  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.23.25  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.23.50  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.23.52  255.255.255.252     10.1.114.144     10.1.114.146    257
       10.1.23.92  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.23.97  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.23.98  255.255.255.255     10.1.114.144     10.1.114.146    257
      10.1.23.109  255.255.255.255     10.1.114.144     10.1.114.146    257
       10.1.114.0    255.255.255.0            在链路上      10.1.114.146    257
     10.1.114.146  255.255.255.255            在链路上      10.1.114.146    257
     10.1.114.255  255.255.255.255            在链路上      10.1.114.146    257
     10.126.126.0    255.255.255.0            在链路上      10.126.126.2    261
     10.126.126.2  255.255.255.255            在链路上      10.126.126.2    261
   10.126.126.255  255.255.255.255            在链路上      10.126.126.2    261
        127.0.0.0        255.0.0.0            在链路上         127.0.0.1    331
        127.0.0.1  255.255.255.255            在链路上         127.0.0.1    331
  127.255.255.255  255.255.255.255            在链路上         127.0.0.1    331
      172.16.50.0    255.255.255.0            在链路上      172.16.50.83    281
     172.16.50.83  255.255.255.255            在链路上      172.16.50.83    281
    172.16.50.255  255.255.255.255            在链路上      172.16.50.83    281
     192.168.10.0    255.255.255.0            在链路上      192.168.10.1    291
     192.168.10.1  255.255.255.255            在链路上      192.168.10.1    291
   192.168.10.255  255.255.255.255            在链路上      192.168.10.1    291
     192.168.20.0    255.255.255.0            在链路上      192.168.20.1    291
     192.168.20.1  255.255.255.255            在链路上      192.168.20.1    291
   192.168.20.255  255.255.255.255            在链路上      192.168.20.1    291
     192.168.56.0    255.255.255.0            在链路上      192.168.56.1    281
     192.168.56.1  255.255.255.255            在链路上      192.168.56.1    281
   192.168.56.255  255.255.255.255            在链路上      192.168.56.1    281
       198.18.0.0      255.255.0.0          2.0.0.4          2.0.0.1    257
        224.0.0.0        240.0.0.0            在链路上         127.0.0.1    331
        224.0.0.0        240.0.0.0            在链路上      192.168.56.1    281
        224.0.0.0        240.0.0.0            在链路上      192.168.20.1    291
        224.0.0.0        240.0.0.0            在链路上      192.168.10.1    291
        224.0.0.0        240.0.0.0            在链路上      172.16.50.83    281
        224.0.0.0        240.0.0.0            在链路上      10.1.114.146    257
        224.0.0.0        240.0.0.0            在链路上      10.126.126.2    261
  255.255.255.255  255.255.255.255            在链路上         127.0.0.1    331
  255.255.255.255  255.255.255.255            在链路上      192.168.56.1    281
  255.255.255.255  255.255.255.255            在链路上      192.168.20.1    291
  255.255.255.255  255.255.255.255            在链路上      192.168.10.1    291
  255.255.255.255  255.255.255.255            在链路上      172.16.50.83    281
  255.255.255.255  255.255.255.255            在链路上      10.1.114.146    257
  255.255.255.255  255.255.255.255            在链路上      10.126.126.2    261
===========================================================================
永久路由:
  网络地址          网络掩码  网关地址  跃点数
          0.0.0.0          0.0.0.0      172.16.50.1     默认
===========================================================================";
    let filter = Regex::new("^ +(?P<dest>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?P<netmask>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?P<next>\\S+) +(?P<from>(?:[0-9]+\\.){3}(?:[0-9]+)) +(?:[0-9]+)$").unwrap();
    for line in output3.split("\n").collect::<Vec<&str>>() {
        if let Some(c) = filter.captures(line) {
            println!(
                "dest: ({}) netmask: ({}) next: ({}) from: ({})",
                &c["dest"], &c["netmask"], &c["next"], &c["from"]
            );
        }
    }
}

#[test]
fn test_parse_netmask() {
    let ip = "0.0.0.0".parse::<Ipv4Addr>().unwrap();
    println!("ip: {}", ip.to_bits());
}

#[test]
fn test_regexp_cap() {
    let output = "0.0.0.0 via 172.16.175.253 dev eth0 proto dhcp src 172.16.163.87 metric 100";
    let reg_via = Regex::new("via (?P<via>(?:[0-9]+\\.){3}(?:[0-9]+))").unwrap();
    let reg_dev = Regex::new("dev (?P<dev>[a-z0-9]+)").unwrap();
    let reg_src = Regex::new("src (?P<src>(?:[0-9]+\\.){3}(?:[0-9]+))").unwrap();
    let reg_cidr = Regex::new("^([0-9]+\\.){3}([0-9]+)(/[0-9]*|)").unwrap();

    if let Some(via) = reg_via.captures(output) {
        println!("{}: {}", via.len(), &via["via"]);
    }
    if let Some(dev) = reg_dev.captures(output) {
        println!("{}: {}", dev.len(), &dev["dev"]);
    }
    if let Some(src) = reg_src.captures(output) {
        println!("{}: {}", src.len(), &src["src"]);
    }
    if let Some(cidr) = reg_cidr.find(output) {
        println!("{}", cidr.as_str());
    }
}

#[test]
fn test_parse_ipport() {
    let ip = "127.0.0.1:9980".parse::<IPPort>().unwrap();
    println!("ip: {:?}", ip);
    let ip2 = IPPort{
        ip: Ipv4Addr::new(10,10,10,10),
        port: 9980,
    };
    println!("ip2 == ip: {}", ip2 == ip);
    let ip3 = ip2.clone();
    println!("ip3 == ip2: {}", ip3 == ip2);
}
